package net.cyue.easyconfiguration.json;

import com.fasterxml.jackson.databind.JsonNode;
import net.cyue.easyconfiguration.api.IConfigurationResource;
import net.cyue.easyconfiguration.json.util.JSONUtil;
import net.cyue.easyconfiguration.node.NodeType;
import net.cyue.util.ResourceUtil;
import net.cyue.util.StreamUtil;
import net.cyue.util.StringUtil;

import java.io.IOException;
import java.io.InputStream;
import java.util.*;

public class JSONConfigurationResource implements IConfigurationResource {

    private final JsonNode rootNode;

    public JSONConfigurationResource(String json) throws IOException {
        this.rootNode = JSONUtil.parse(json);
    }
    public JSONConfigurationResource(InputStream inputStream) throws IOException {
        this(StreamUtil.readAsString(inputStream));
    }

    public static JSONConfigurationResource fromResource(String resourceName) throws IOException {
        return new JSONConfigurationResource(ResourceUtil.getResourceAsStream(resourceName));
    }

    @Override
    public NodeType getNodeType(String path) {
        JsonNode node = rootNode.get(path);
        if (node == null) {
            return NodeType.ANY;
        } else if (node.isObject()) {
            return NodeType.TABLE;
        } else if (node.isArray()) {
            return NodeType.ARRAY;
        } else if (node.isTextual()) {
            return NodeType.STRING;
        } else if (node.isNumber()) {
            return NodeType.NUMBER;
        } else if (node.isBoolean()) {
            return NodeType.BOOLEAN;
        }
        return NodeType.ANY;
    }

    @Override
    public List<String> getTableKeyList(String tablePath) {
        if (StringUtil.isBlank(tablePath) || tablePath.trim().equals("*")) {
            return JSONUtil.getObjectFieldNameList(rootNode);
        }
        JsonNode node = JSONUtil.getNode(rootNode, tablePath);
        return JSONUtil.getObjectFieldNameList(node);
    }

    @Override
    public Object get(String path) {
        return JSONUtil.getNodeValue(rootNode, path);
    }

    @Override
    public String getString(String path) {
        return JSONUtil.getString(rootNode, path);
    }

    @Override
    public Number getNumber(String path) {
        return JSONUtil.getNumber(rootNode, path);
    }

    @Override
    public Boolean getBoolean(String path) {
        return JSONUtil.getBoolean(rootNode, path);
    }

    @Override
    public Object[] getArray(String path) {
        return JSONUtil.getArray(rootNode, path).toArray();
    }

    @Override
    public Map<String, Object> getTable(String path) {
        return JSONUtil.getTable(rootNode, path);
    }

}
